// Copyright (c) 2004 Dmitry Shuklin. All rights reserved.
using System;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Direct3D = Microsoft.DirectX.Direct3D;

namespace Cerebrum.Direct3D.Forms
{
	/// <summary>
	/// Summary description for Splitter.
	/// </summary>
	public class Splitter : Cerebrum.Direct3D.Forms.Control 
	{
		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

		public Splitter(System.ComponentModel.IContainer container)
		{
			///
			/// Required for Windows.Forms Class Composition Designer support
			///
			container.Add(this);
			InitializeComponent();

			//
			// TODO: Add any constructor code after InitializeComponent call
			//
		}

		public Splitter()
		{
			///
			/// Required for Windows.Forms Class Composition Designer support
			///
			InitializeComponent();

			//
			// TODO: Add any constructor code after InitializeComponent call
			//
		}

		/// <summary> 
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}


		#region Component Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			components = new System.ComponentModel.Container();
			this.ForeColor = Color.Khaki;
		}
		#endregion


		protected Cerebrum.Direct3D.Forms.Control m_Target = null;
		protected float m_ExtraLimit;
		//protected float m_IntraLimit;
#warning "intralimit not working yet"

		protected void BeginSplit()
		{
			m_Target = null;
			Cerebrum.Direct3D.Forms.Control _Extra = null;

			Cerebrum.Direct3D.Forms.Control parent = this.Parent;
			if(parent!=null)
			{
			
				System.Windows.Forms.DockStyle _ndock = System.Windows.Forms.DockStyle.Fill;
				switch(this.Dock)
				{
					case System.Windows.Forms.DockStyle.Bottom:
					{
						_ndock = System.Windows.Forms.DockStyle.Top;
						break;
					}
					case System.Windows.Forms.DockStyle.Right:
					{
						_ndock = System.Windows.Forms.DockStyle.Left;
						break;
					}
					case System.Windows.Forms.DockStyle.Top:
					{
						_ndock = System.Windows.Forms.DockStyle.Bottom;
						break;
 
					}
					case System.Windows.Forms.DockStyle.Left:
					{
						_ndock = System.Windows.Forms.DockStyle.Right;
						break;
 
					}
				}

				int _thisIndex = parent.Controls.Count;
				for(int i=0; i < parent.Controls.Count; i++)
				{
					Cerebrum.Direct3D.Forms.Control ctl = parent.Controls[i];
					if(ctl==this) _thisIndex = i;
					if(ctl is Splitter) continue;
					if(i > _thisIndex)
					{
						if(m_Target == null && this.Dock == ctl.Dock) m_Target = ctl;
					}
					if(_Extra == null && _ndock == ctl.Dock) _Extra = ctl;
					if(m_Target != null && _Extra != null) break;
				}
				if(m_Target != null)
				{
					switch(this.Dock)
					{
						case System.Windows.Forms.DockStyle.Bottom:
						{
							if(_Extra != null)
							{
								m_ExtraLimit = _Extra.DisplayRectangle.Bottom;
							}
							else
							{
								m_ExtraLimit = this.Parent.DisplayRectangle.Top;
							}
							break;
						}
						case System.Windows.Forms.DockStyle.Right:
						{
							if(_Extra != null)
							{
								m_ExtraLimit = _Extra.DisplayRectangle.Right;
							}
							else
							{
								m_ExtraLimit = this.Parent.DisplayRectangle.Left;
							}
							break;
						}
						case System.Windows.Forms.DockStyle.Top:
						{
							if(_Extra != null)
							{
								m_ExtraLimit = _Extra.DisplayRectangle.Top;
							}
							else
							{
								m_ExtraLimit = this.Parent.DisplayRectangle.Bottom;
							}
							break;
 
						}
						case System.Windows.Forms.DockStyle.Left:
						{
							if(_Extra != null)
							{
								m_ExtraLimit = _Extra.DisplayRectangle.Left;
							}
							else
							{
								m_ExtraLimit = this.Parent.DisplayRectangle.Right;
							}
							break;
 
						}
					}				
				}
			}
		}

		protected float m_MinSize = 16;
		public float MinSize
		{
			get
			{
				return m_MinSize;
			}
			set
			{
				m_MinSize = value;
			}
		}
		protected float m_MaxExtra = 16;
		public float MaxExtra
		{
			get
			{
				return m_MaxExtra;
			}
			set
			{
				m_MaxExtra = value;
			}
		}

		protected Point m_DownMousePosition;
		protected SizeF m_TargetSize;
		protected bool m_MouseDown = false;

		protected internal override void OnMouseDown(MouseEventArgs e)
		{
			base.OnMouseDown (e);
			m_DownMousePosition.X = e.X + (int)this.SurfaceRectangle.X;
			m_DownMousePosition.Y = e.Y + (int)this.SurfaceRectangle.Y;
			this.BeginSplit();
			if(m_Target!=null)
			{
				m_MouseDown = true;
				m_TargetSize = m_Target.Size;
			}
		}

#warning "vertical dock not working yet"
		protected internal override void OnMouseMove(MouseEventArgs e)
		{
			base.OnMouseMove (e);
			if(m_MouseDown)
			{
				if(m_Target!=null)
				{
					RectangleF _rect = m_Target.DisplayRectangle;
					SizeF _size = this.DisplayRectangle.Size;

					switch (m_Target.Dock)
					{
						case System.Windows.Forms.DockStyle.Bottom:
						{
							float v = m_TargetSize.Height + m_DownMousePosition.Y - (e.Y + this.SurfaceRectangle.Y);
							if(_rect.Bottom - v - m_MaxExtra - _size.Height < m_ExtraLimit) v = _rect.Bottom - m_ExtraLimit - m_MaxExtra - _size.Height;
							if(v < m_MinSize) v = m_MinSize;
							m_Target.SetBounds(_rect.X, _rect.Y, _rect.Width, v, System.Windows.Forms.BoundsSpecified.Height);
							break;
						}
						case System.Windows.Forms.DockStyle.Right:
						{
							float v = m_TargetSize.Width + m_DownMousePosition.X - (e.X + this.SurfaceRectangle.X);
							if(_rect.Right - v - m_MaxExtra - _size.Width < m_ExtraLimit) v = _rect.Right - m_ExtraLimit - m_MaxExtra - _size.Width;
							if(v < m_MinSize) v = m_MinSize;
							m_Target.SetBounds(_rect.X, _rect.Y, v, _rect.Height, System.Windows.Forms.BoundsSpecified.Width);
							break;
						}
						case System.Windows.Forms.DockStyle.Top:
						{
							float v = m_TargetSize.Height + (e.Y + this.SurfaceRectangle.Y)- m_DownMousePosition.Y;
							if(_rect.Y + v + m_MaxExtra + _size.Height > m_ExtraLimit) v = m_ExtraLimit - _rect.Y - m_MaxExtra - _size.Height;
							if(v < m_MinSize) v = m_MinSize;
							m_Target.SetBounds(_rect.X, _rect.Y, _rect.Width,  v, System.Windows.Forms.BoundsSpecified.Height);
							break;
 
						}
						case System.Windows.Forms.DockStyle.Left:
						{
							float v = m_TargetSize.Width + m_DownMousePosition.X - (e.X + this.SurfaceRectangle.X);
							if(_rect.X + v + m_MaxExtra + _size.Width > m_ExtraLimit) v = m_ExtraLimit - _rect.X - m_MaxExtra - _size.Width;
							if(v < m_MinSize) v = m_MinSize;
							m_Target.SetBounds(_rect.X, _rect.Y, v, _rect.Height, System.Windows.Forms.BoundsSpecified.Width);
							break;
						}

					}
					this.Invalidate();
				}
			}
		}

		
		protected override void OnPerformLayout(EventArgs e)
		{
			base.OnPerformLayout (e);
			if(!m_MouseDown)
			{
				this.BeginSplit();
				if(m_Target!=null)
				{
					RectangleF _rect = m_Target.DisplayRectangle;
					SizeF _size = this.DisplayRectangle.Size;
					SizeF _targetSize = _rect.Size;
					
					//if(m_TargetSize.Width < 0.1f && m_TargetSize.Height < 0.1f) m_TargetSize = _rect.Size;

					switch (m_Target.Dock)
					{
						case System.Windows.Forms.DockStyle.Bottom:
						{
							float v = _targetSize.Height;
							if(_rect.Bottom - v - m_MaxExtra - _size.Height < m_ExtraLimit) v = _rect.Bottom - m_ExtraLimit - m_MaxExtra - _size.Height;
							if(v < m_MinSize) v = m_MinSize;
							m_Target.SetBounds(_rect.X, _rect.Y, _rect.Width, v, System.Windows.Forms.BoundsSpecified.Height);
							//this.SetBounds(0, m_Target.DisplayRectangle.Top - this.DisplayRectangle.Height, 0, 0, System.Windows.Forms.BoundsSpecified.Y);
							break;
						}
						case System.Windows.Forms.DockStyle.Right:
						{
							float v = _targetSize.Width;
							if(_rect.Right - v - m_MaxExtra - _size.Width < m_ExtraLimit) v = _rect.Right - m_ExtraLimit - m_MaxExtra - _size.Width;
							if(v < m_MinSize) v = m_MinSize;
							m_Target.SetBounds(_rect.X, _rect.Y, v, _rect.Height, System.Windows.Forms.BoundsSpecified.Width);
							//this.SetBounds(m_Target.DisplayRectangle.Left - this.DisplayRectangle.Width, 0, 0, 0, System.Windows.Forms.BoundsSpecified.X);
							break;
						}
						case System.Windows.Forms.DockStyle.Top:
						{
							float v = _targetSize.Height;
							if(_rect.Y + v + m_MaxExtra + _size.Height > m_ExtraLimit) v = m_ExtraLimit - _rect.Y - m_MaxExtra - _size.Height;
							if(v < m_MinSize) v = m_MinSize;
							m_Target.SetBounds(_rect.X, _rect.Y, _rect.Width,  v, System.Windows.Forms.BoundsSpecified.Height);
							//this.SetBounds(0, m_Target.DisplayRectangle.Bottom, 0, 0, System.Windows.Forms.BoundsSpecified.Y);
							break;
 
						}
						case System.Windows.Forms.DockStyle.Left:
						{
							float v = _targetSize.Width;
							if(_rect.X + v + m_MaxExtra + _size.Width > m_ExtraLimit) v = m_ExtraLimit - _rect.X - m_MaxExtra - _size.Width;
							if(v < m_MinSize) v = m_MinSize;
							m_Target.SetBounds(_rect.X, _rect.Y, v, _rect.Height, System.Windows.Forms.BoundsSpecified.Width);
							//this.SetBounds(m_Target.DisplayRectangle.Right, 0, 0, 0, System.Windows.Forms.BoundsSpecified.X);
							break;
						}
					}
				}
			}
		}


		protected internal override void OnMouseUp(MouseEventArgs e)
		{
			m_MouseDown = false;

			base.OnMouseUp (e);

			if(m_Target!=null)
			{
				m_TargetSize = m_Target.Size;
				m_Target = null;
			}
		}



		protected override void OnRenderScene(Cerebrum.Direct3D.Forms.RenderEventArgs e)
		{

			Cerebrum.Direct3D.Drawing.Graphics _Graphics = Cerebrum.Direct3D.Drawing.Graphics.FromDevice(e.Device);
			_Graphics.DrawRectangle(this.SurfaceRectangle, this.m_Z, this.m_ForeColor, true);

			base.OnRenderScene (e);
		}
	}
}
